package br.org.bertol.orion.admin;

import java.io.File;
import java.io.InputStream;
import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.Map;
import oracle.oc4j.admin.internal.UnDeployerFactory;
import oracle.oc4j.admin.internal.UnDeployerIF;
import oracle.oc4j.admin.internal.UploaderStateKeeper;
import oracle.oc4j.admin.jmx.shared.util.DataSink;
import oracle.oc4j.admin.management.shared.SharedModuleType;
import br.org.bertol.orion.admin.internal.OrionDeployerFactory;
import br.org.bertol.orion.admin.internal.OrionDeployerIF;
import com.evermind.naming.archive.ContentArchiveContext;
import com.evermind.server.ApplicationServer;
import com.evermind.server.administration.ApplicationServerAdministrator;
import com.evermind.server.administration.DefaultApplicationServerAdministrator;

public class OrionApplicationServerAdministrator
    extends DefaultApplicationServerAdministrator
    implements ApplicationServerAdministrator
{

	public OrionApplicationServerAdministrator (ApplicationServer server)
	{
		super(server);
	}

	public Map deploy (Integer id, String applicationName, Map extraParameters)
	    throws RemoteException
	{
		File uploadFile = (File)UploaderStateKeeper.getState(id);
		DataSink sink = new DataSink(uploadFile.getAbsolutePath());
		sink.setUploadId(id);
		return internalDeploy(sink, applicationName, extraParameters, SharedModuleType.EAR);
	}

	public Map deploy (byte data[], String applicationName, Map extraParameters)
	    throws RemoteException
	{
		DataSink sink = new DataSink(data);
		return internalDeploy(sink, applicationName, extraParameters, SharedModuleType.EAR);
	}

	public Map deploy (String earFilePath, String applicationName) throws RemoteException
	{
		return deploy(earFilePath, applicationName, null);
	}

	public Map deploy (String earFilePath, String applicationName, Map extraParameters)
	    throws RemoteException
	{
		if (earFilePath.endsWith(".rar"))
		{
			DataSink sink = new DataSink(earFilePath);
			return internalDeploy(sink, applicationName, extraParameters, SharedModuleType.RAR);
		}
		if (extraParameters != null && extraParameters.containsKey("isRar")
		    && "true".equals(extraParameters.get("isRar")))
		{
			byte data[];
			try
			{
				data = extractRarFile(earFilePath, (String)extraParameters.get("rarPath"));
			}
			catch (Exception e)
			{
				throw new RemoteException("Unable to extract rar file", e);
			}
			DataSink sink = new DataSink(data);
			return internalDeploy(sink, applicationName, extraParameters, SharedModuleType.RAR);
		}
		else
		{
			DataSink sink = new DataSink(earFilePath);
			return internalDeploy(sink, applicationName, extraParameters, SharedModuleType.EAR);
		}
	}

	public Map deploy (InputStream appStream, String applicationName, String parentApp,
	    String bindto) throws Exception
	{
		final HashMap extraParams = new HashMap();

		if (!"default".equals(parentApp)) extraParams.put("parent", parentApp);

		if (bindto != null) extraParams.put("bindWebApp", bindto);

		final DataSink sink = new DataSink(appStream);

		return internalDeploy(sink, applicationName, extraParams, SharedModuleType.EAR);
	}

	public void undeploy (String appName, boolean removeFiles) throws RemoteException
	{
		internalUndeploy(appName, removeFiles, SharedModuleType.EAR);
	}

	public void undeployConnector (String deployName, boolean removeFiles) throws RemoteException
	{
		internalUndeploy(deployName, removeFiles, SharedModuleType.RAR);
	}

	private Map internalDeploy (final DataSink sink, final String deployName, final Map extraParams,
	    final SharedModuleType type) throws RemoteException
	{
		try
		{
			OrionDeployerIF deployer = OrionDeployerFactory.getInstance(server, sink, deployName,
			    type, extraParams);
			return deployer.execute(true);
		}
		catch (Exception e)
		{
			throw new RemoteException("deploy failed!: ", e);
		}
	}

	private void internalUndeploy (String deployName, boolean removeFiles, SharedModuleType type)
	    throws RemoteException
	{
		try
		{
			UnDeployerIF undeployer = UnDeployerFactory.getInstance(server, deployName, type);
			undeployer.execute();
		}
		catch (Exception e)
		{
			throw new RemoteException("undeploy failed!: ", e);
		}
	}

	private byte[] extractRarFile (String earFilePath, String rarPath) throws Exception
	{
		File file = new File(earFilePath);
		ContentArchiveContext context = new ContentArchiveContext(file, true);
		return (byte[])context.lookup(rarPath);
	}

}
